package blog

import (
	"context"
	"encoding/json"
	"strconv"

	"gitee.com/go-course/go12/vblog/common"
)

const (
	AppName = "blogs"
)

// 博客模块接口
type Service interface {
	// 创建博客
	CreateBlog(context.Context, *CreateBlogRequest) (*Blog, error)
	// 查询文章列表, 列表查询, 没有必要查询文章的具体内容
	QueryBlog(context.Context, *QueryBlogRequest) (*BlogSet, error)
	// 详情页, 尽量多的把关联的数据查询出来， content
	DescribeBlog(context.Context, *DescribeBlogRequest) (*Blog, error)
	// 修改文章状态
	UpdateBlogStatus(context.Context, *UpdateBlogStatusRequest) (*Blog, error)
	// 更新文章
	UpdateBlog(context.Context, *UpdateBlogRequest) (*Blog, error)
	// 删除文档
	DeleteBlog(context.Context, *DeleteBlogRequest) error
	// 文章审核, 审核通过的文章才能被看到
	AuditBlog(context.Context, *AuditBlogRequest) (*Blog, error)
}

func NewAuditBlogRequest(id string) *AuditBlogRequest {
	return &AuditBlogRequest{
		BlogId: id,
	}
}

type AuditBlogRequest struct {
	// 审核的文章
	BlogId string `json:"blog_id"`
	// 是否审核成功
	IsAuditPass bool `json:"is_audit_pass"`
}

func NewDescribeBlogRequest(id string) *DescribeBlogRequest {
	return &DescribeBlogRequest{
		BlogId: id,
	}
}

type DescribeBlogRequest struct {
	BlogId string `json:"blog_id"`
}

func NewBlogSet() *BlogSet {
	return &BlogSet{
		Items: []*Blog{},
	}
}

type BlogSet struct {
	// 博客的总数
	Total int64 `json:"total"`
	// 返回的一页的数据
	Items []*Blog `json:"items"`
}

func (b *BlogSet) String() string {
	dj, _ := json.Marshal(b)
	return string(dj)
}

func (s *BlogSet) Add(items ...*Blog) {
	s.Items = append(s.Items, items...)
}

func NewQueryBlogRequest() *QueryBlogRequest {
	return &QueryBlogRequest{
		PageSize:   10,
		PageNumber: 1,
		Usernames:  []string{},
	}
}

// 后端分页
type QueryBlogRequest struct {
	// 利用数据库的offst limit, 去数据库里面获取一页的数据
	// 页的大小
	PageSize int `json:"page_size"`
	// 当前处于几页
	PageNumber int `json:"page_number"`
	// 0 表示草稿状态, 要查询所有的博客
	// nil 没有这个过滤条件
	// 0   DRAFT
	// 1   PUBLISHED
	Status *Status `json:"status"`
	// 基于文章标题的关键字搜索
	Keywords string `json:"keywords"`
	// 查询属于哪些用户的博客
	Usernames []string `json:"Usernames"`
}

// 依赖, 根据分页大小,当前页数 可以推导出 获取元素的开始和结束位置
// [1,2,3,4,5] [6,7,8,9,10] [11,12,13,14,15]
// limite(offset, limte) limite(5 * 0,5) [1,2,3,4,5]
// limite(5*1,5) [6,7,8,9,10]
// limite(5*2,5)  [11,12,13,14,15]
func (r *QueryBlogRequest) Offset() int {
	return int(r.PageSize * (r.PageNumber - 1))
}

func (r *QueryBlogRequest) AddUsername(usernames ...string) {
	r.Usernames = append(r.Usernames, usernames...)
}

func (r *QueryBlogRequest) ParsePageSize(ps string) {
	psInt, _ := strconv.ParseInt(ps, 10, 64)
	if psInt != 0 {
		r.PageSize = int(psInt)
	}
}

func (r *QueryBlogRequest) ParsePageNumber(pn string) {
	psInt, _ := strconv.ParseInt(pn, 10, 64)
	if psInt != 0 {
		r.PageNumber = int(psInt)
	}
}

func (r *QueryBlogRequest) SetStatus(s Status) {
	r.Status = &s
}

type UpdateBlogStatusRequest struct {
	// 如果定义一篇文章, 使用对象Id, 具体的某一篇文章
	BlogId int64 `json:"blog_id"`
	// 修改的状态: DRAFT/PUBLISHED
	Status Status `json:"status"`
}

func NewPutUpdateBlogRequest(id string) *UpdateBlogRequest {
	return &UpdateBlogRequest{
		BlogId:            id,
		UpdateMode:        UPDATE_MODE_PUT,
		CreateBlogRequest: NewCreateBlogRequest(),
	}
}

func NewPatchUpdateBlogRequest(id string) *UpdateBlogRequest {
	return &UpdateBlogRequest{
		BlogId:            id,
		UpdateMode:        UPDATE_MODE_PATCH,
		CreateBlogRequest: NewCreateBlogRequest(),
	}
}

type UpdateBlogRequest struct {
	// 如果定义一篇文章, 使用对象Id, 具体的某一篇文章
	BlogId string `json:"blog_id"`
	// blog的范围, 不是用户传递进来的, 是api接口层 自动填充
	Scope *common.Scope `json:"scope"`
	// 更新方式 区分全量更新/增量更新
	UpdateMode UpdateMode `json:"update_mode"`
	// 用户更新请求, 用户只传了个标签
	*CreateBlogRequest
}

func NewDeleteBlogRequest(id string) *DeleteBlogRequest {
	return &DeleteBlogRequest{
		BlogId: id,
	}
}

type DeleteBlogRequest struct {
	// 如果定义一篇文章, 使用对象Id, 具体的某一篇文章
	BlogId string `json:"blog_id"`
}
